﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Collections;
using Psl.Controls;
using System.Runtime.Serialization.Formatters.Soap;
using System.IO;
using System.Runtime.Serialization;

namespace Stl.Controls
{
    /// <summary>
    /// Cette classe propose des fonctionnalités pour sérialiser un contrôle en utilisant ControlWrapper.
    /// </summary>
    public class DesignSerializer
    {
        /// <summary>
        /// Format de sérialisation.
        /// </summary>
        public static DataFormats.Format Format
        {
            get { return DataFormats.GetFormat(typeof(ControlWrapper).FullName); }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="cw"></param>
        /// <returns></returns>
        private static string DoSerialize(ControlWrapper cw)
        {
            using (MemoryStream stream = new MemoryStream())
            {
                IFormatter formatter = new SoapFormatter();
                formatter.Serialize(stream, cw);
                return Encoding.ASCII.GetString(stream.GetBuffer());
            }
        }

        /// <summary>
        /// Permet de sérialiser plusieurs contrôles.
        /// </summary>
        /// <param name="controls"></param>
        /// <returns></returns>
        public static string ControlsToString(IEnumerable controls)
        {
            if (controls == null) return "";
            ControlWrapper cw = ControlWrapper.Wrap(controls);
            return DoSerialize(cw);
        }

        /// <summary>
        /// Permet de sériéliser un contrôle.
        /// </summary>
        /// <param name="control"></param>
        /// <returns></returns>
        public static string ControlToString(Control control)
        {
            if (control == null) return "";
            ControlWrapper cw = ControlWrapper.Wrap(control);
            return DoSerialize(cw);
        }

        /// <summary>
        /// Déserialize plusieurs contrôles.
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static Control[] StringToControls(string value)
        {
            if (value == null) return null;
            using (MemoryStream stream = new MemoryStream(Encoding.ASCII.GetBytes(value)))
            {
                IFormatter formatter = new SoapFormatter();
                Object obj = formatter.Deserialize(stream);
                if (obj == null) return null;
                return (obj as ControlWrapper).Controls;
            }
        }

        /// <summary>
        /// Déserialize un contrôle.
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static Control StringToControl(string value)
        {
            if (value == null) return null;
            using (MemoryStream stream = new MemoryStream(Encoding.ASCII.GetBytes(value)))
            {
                IFormatter formatter = new SoapFormatter();
                Object obj = formatter.Deserialize(stream);
                if (obj == null) return null;
                return (obj as ControlWrapper).Control;
            }
        }

        /// <summary>
        /// Mémorise le contrôle dans le clipboard.
        /// </summary>
        /// <param name="control"></param>
        public static void ControlToClipboard(Control control)
        {
            string serialized = ControlToString(control);                           // chaîne de sérialisation Soap
            IDataObject dataObject = new DataObject();                              // créer l’objet pour le clipboard
            if(serialized != "")    // ne pas expose si le control est null
                dataObject.SetData(Format.Name, true, serialized);                  // premier format
            dataObject.SetData(DataFormats.Text, true, serialized);                 // second  format
            Clipboard.SetDataObject(dataObject, false);
        }

        /// <summary>
        /// Récupère le contrôle depuis le clipboard.
        /// </summary>
        /// <returns></returns>
        public static Control ClipboardToControl()
        {
            Object obj = Clipboard.GetData(Format.Name);
            return StringToControl(obj as string);
        }

        /// <summary>
        /// Stoque les contrôles dans un fichier.
        /// </summary>
        /// <param name="filename"></param>
        /// <param name="controls"></param>
        public static void ControlsToFile(string filename, IEnumerable controls)
        {
            string serialized = ControlsToString(controls);
            try
            {
                TextWriter writer = new StreamWriter(filename);
                writer.Write(serialized);
            }
            catch(Exception e)
            {
                MessageBox.Show(e.Message);
            }
        }

        /// <summary>
        /// Récupère les contrôles depuis un fichier.
        /// </summary>
        /// <param name="filename"></param>
        /// <returns></returns>
        public static Control[] FileToControls(string filename)
        {
            try
            {
                TextReader reader = new StreamReader(filename);
                string data = reader.ReadToEnd();
                return StringToControls(data);
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
                return null;
            }
        }
    }
}
